package com.fine.demo.temperaturepolyline;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TemperaturePolyline extends View {

    /*
     * 折线的段数（温度数-1就是折线的段数）
     * 例如需要画7个线段就需要八天的温度
     */
    private int polylineNum = 7;

    private int mViewWidth, mViewHeight;    //控件的宽高
    private List<Integer> temperatures;     //温度数值

    private int mMaxTemp, mMinTemp;     //最大最小值温度
    private final String TEMPERATURE_UNIT = "℃";

    //绘制相关
    private Paint mPointPaint;  //圆点画笔
    private float TEXT_HEIGHT = 30; //显示的文字距离点的高度
    private float TEXT_WIDTH = 30;
    private Paint mLinePaint;   //直线画笔
    private Paint mTextPaint;   //文字画笔

    private Point currentPoint, previousPoint;

    //属性相关
    private boolean textUp = true;
    private int mPointColor;    //圆点颜色
    private int mLineColor;     //直线颜色
    private int mTextColor;     //文字颜色
    private float POINT_RADIUS = 10F;   //圆点半径
    private float LINE_WIDTH = 5F;      //直线宽度
    private float TEXT_SIZE = 24F;      //文字大小

    public TemperaturePolyline(Context context) {
        this(context, null);
    }

    public TemperaturePolyline(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TemperaturePolyline(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData(context, attrs);
    }

    private void initData(Context context, @Nullable AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TemperaturePolyline);
        mPointColor = array.getColor(R.styleable.TemperaturePolyline_pointColor, Color.BLUE);
        mLineColor = array.getColor(R.styleable.TemperaturePolyline_lineColor, Color.BLUE);
        mTextColor = array.getColor(R.styleable.TemperaturePolyline_textColor, Color.BLACK);
        POINT_RADIUS = array.getDimension(R.styleable.TemperaturePolyline_pointRadius, 10F);
        LINE_WIDTH = array.getDimension(R.styleable.TemperaturePolyline_lineWidth, 5F);
        TEXT_SIZE = array.getDimension(R.styleable.TemperaturePolyline_textSize, 24F);
        textUp = array.getBoolean(R.styleable.TemperaturePolyline_textUp, true);
        array.recycle();

        initPaint();

        //坐标点
        currentPoint = new Point();
        previousPoint = new Point();
    }

    /**
     * 初始化各个画笔
     */
    private void initPaint() {
        temperatures = new ArrayList<>();
        //初始化圆点画笔
        mPointPaint = new Paint();
        mPointPaint.setColor(mPointColor);
        mPointPaint.setStyle(Paint.Style.FILL);
        //初始化直线
        mLinePaint = new Paint();
        mLinePaint.setColor(mLineColor);
        mLinePaint.setStyle(Paint.Style.FILL);
        mLinePaint.setStrokeWidth(LINE_WIDTH);
        mLinePaint.setAntiAlias(true);    //设置抗锯齿
        //初始化文字
        mTextPaint = new Paint();
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(TEXT_SIZE);
        mTextPaint.setStrokeWidth(0);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        TEXT_HEIGHT = fontMetrics.descent - fontMetrics.ascent + fontMetrics.leading;
        TEXT_WIDTH = mTextPaint.measureText("10" + TEMPERATURE_UNIT);
    }

    /**
     * 设置温度文字是在圆点的上面显示还是下面显示
     * @param textUp boolean
     */
    public void setTextUp(boolean textUp) {
        this.textUp = textUp;
    }

    public void refreshTemperature(List<Integer> temperatures) {
        this.temperatures.addAll(temperatures);
        mMaxTemp = Collections.max(this.temperatures);
        mMinTemp = Collections.min(this.temperatures);
        polylineNum = this.temperatures.size() - 1;
        if(mMaxTemp == mMinTemp) {  //防止出现温度全部相等的情况，被除数为0
            mMaxTemp = mMaxTemp + 1;
        }
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mViewHeight = getMeasuredHeight();
        setMeasuredDimension(mViewWidth, mViewHeight);
    }

    public void setViewWidth(int viewWidth) {
        this.mViewWidth = viewWidth;
        requestLayout();
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(temperatures.isEmpty()) {
            return;
        }
        //(控件的宽度-两边的预留大小-两边圆点的半径)/直线的个数
        int unitX = (mViewWidth - 20 - (int)POINT_RADIUS * 2 - (int)TEXT_WIDTH / 2) / polylineNum;
        //(控件高度-文字高度和预留边框 - 最大最小温度圆点的半径)/ (最大温度- 最小温度)
        int unitY = (mViewHeight - (int)TEXT_HEIGHT - 20 - (int)POINT_RADIUS * 2) / (mMaxTemp - mMinTemp);;
        for (int i = 0; i < temperatures.size(); i++) {
            currentPoint.x = i * unitX + (int)POINT_RADIUS * 2 + (int)TEXT_WIDTH / 2;    //开始坐标是 点的位置*标准长度 + 温度圆点的直径 + 文字宽度的一半
            //高度坐标是（最大温度-当前点的温度）* 标准高度 + 圆点直径 + 文字高度
            if(textUp) {
                currentPoint.y = (mMaxTemp - temperatures.get(i)) * unitY + (int)POINT_RADIUS * 2 + (int)TEXT_HEIGHT;
            } else {
                currentPoint.y = (mMaxTemp - temperatures.get(i)) * unitY + (int)POINT_RADIUS * 2;
            }
            drawPoint(canvas, currentPoint);
            drawTemperature(canvas, currentPoint, String.valueOf(temperatures.get(i)));
            if(i != 0) {
                drawLine(canvas, previousPoint, currentPoint);
            }
            previousPoint.x = currentPoint.x;
            previousPoint.y = currentPoint.y;
        }
    }

    private void drawPoint(Canvas canvas, Point point) {
        canvas.drawCircle(point.x / 1.0f, point.y / 1.0f, POINT_RADIUS, mPointPaint);
    }

    private void drawLine(Canvas canvas, Point pointStart, Point pointStop) {
        canvas.drawLine(pointStart.x / 1f, pointStart.y / 1f, pointStop.x / 1f, pointStop.y / 1f, mLinePaint);
    }

    private void drawTemperature(Canvas canvas, Point point, String text) {
        if(textUp) {
            canvas.drawText(text + TEMPERATURE_UNIT, point.x / 1.0f + 5f, point.y / 1.0f - TEXT_HEIGHT / 2.0f, mTextPaint);
        } else {
            canvas.drawText(text + TEMPERATURE_UNIT, point.x / 1.0f + 5f, point.y / 1.0f + TEXT_HEIGHT + POINT_RADIUS * 2, mTextPaint);
        }
    }
}
